﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace NETXPF.Web.WCF
{
    /// <summary>
    /// Provides a way to log errors in WCF services.
    /// Just apply the [LogErrors] attribute to your service and provide an optional ErrorHandler parameter (action that handles the error).
    /// You can also specify the FaultProvider parameter which is an action that provides a fault for an exception.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class LogErrorsAttribute : Attribute, IServiceBehavior,
                                                 IErrorHandler
    {
        /// <summary>
        /// Action performed on error.
        /// </summary>
        public Action<Exception> ErrorHandler { get; set; }
        /// <summary>
        /// Fault provider
        /// </summary>
        public Func<Exception, MessageVersion, Message, Message> FaultProvider { get; set; }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description,
                                                    ServiceHostBase host)
        {
            foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(this);
            }
        }
        bool IErrorHandler.HandleError(Exception error)
        {
            if (ErrorHandler != null)
            {
                ErrorHandler(error);
            }
            else
            {
                NETXPF.Library.Log.Exception(error);
            }
            return false;
        }
        void IErrorHandler.ProvideFault(Exception error, MessageVersion version,
                                                                      ref Message fault)
        {
            if (FaultProvider == null)
            {
                fault = null;
            }
            else
            {
                fault = FaultProvider(error, version, fault);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceDescription"></param>
        /// <param name="serviceHostBase"></param>
        /// <param name="endpoints"></param>
        /// <param name="bindingParameters"></param>
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceDescription"></param>
        /// <param name="serviceHostBase"></param>
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
}
